-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
feat(nextjs): remove tracing from pages router API routes #18394
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
feat(nextjs): remove tracing from pages router API routes #18394
Conversation
2af20e5 to
2516846
Compare
node-overhead report 🧳Note: This is a synthetic benchmark with a minimal express app and does not necessarily reflect the real-world performance impact in an application.
|
c055f2d to
8102dd9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR removes explicit tracing instrumentation from Pages Router API route wrappers (wrapApiHandlerWithSentry) for both Node.js server and Edge runtimes, relying instead on Next.js's built-in OpenTelemetry instrumentation to create transaction spans. The wrappers now only handle error capture, transaction name setting on isolation scope, and route backfilling.
Key Changes:
- Removed manual span creation (
startSpanManual,startSpan) from API route wrappers - Wrappers now set transaction names on isolation scope and use route backfill attributes for parameterized route names
- Updated test expectations to reflect origin change from
'auto.http.nextjs'to'auto'(from Next.js OTEL) - Added comprehensive Next.js 16 Pages Router test application with 36+ test cases
Reviewed changes
Copilot reviewed 74 out of 76 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
packages/nextjs/src/common/pages-router-instrumentation/wrapApiHandlerWithSentry.ts |
Removed tracing logic; now only captures errors and sets transaction metadata via isolation scope and route backfill |
packages/nextjs/src/edge/wrapApiHandlerWithSentry.ts |
Removed tracing logic from edge runtime wrapper; simplified to error monitoring only |
packages/nextjs/src/server/index.ts |
Added SEMANTIC_ATTRIBUTE_SENTRY_SOURCE to route backfill logic to ensure proper transaction source attribution |
packages/nextjs/test/config/withSentry.test.ts |
Deleted unit test that verified explicit span creation (no longer applicable) |
dev-packages/e2e-tests/test-applications/nextjs-13/tests/**/*.test.ts |
Updated assertions to expect 'auto' origin instead of 'auto.http.nextjs' |
dev-packages/e2e-tests/test-applications/create-next-app/tests/**/*.test.ts |
Updated assertions for new tracing behavior with flexible parent span matching |
dev-packages/e2e-tests/test-applications/nextjs-pages-dir/tests/edge-route.test.ts |
Removed runtime context assertions and skipped scope isolation test |
dev-packages/e2e-tests/test-applications/nextjs-16-pages-dir/**/* |
New comprehensive test application with 36 test cases for Next.js 16 Pages Router covering both webpack and turbopack |
dev-packages/e2e-tests/test-applications/nextjs-16-pages-dir/TEST_STATUS.md |
Detailed documentation of test status, known issues, and future work items |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
.../e2e-tests/test-applications/nextjs-16-pages-dir/tests/server/excluded-api-endpoints.test.ts
Outdated
Show resolved
Hide resolved
.../e2e-tests/test-applications/nextjs-16-pages-dir/tests/server/excluded-api-endpoints.test.ts
Outdated
Show resolved
Hide resolved
dev-packages/e2e-tests/test-applications/nextjs-16-pages-dir/tests/edge-route.test.ts
Outdated
Show resolved
Hide resolved
dev-packages/e2e-tests/test-applications/nextjs-16-pages-dir/tests/pages-ssr-errors.test.ts
Outdated
Show resolved
Hide resolved
dev-packages/e2e-tests/test-applications/nextjs-16-pages-dir/tests/proxy.test.ts
Outdated
Show resolved
Hide resolved
dev-packages/e2e-tests/test-applications/nextjs-16-pages-dir/tests/transactions.test.ts
Outdated
Show resolved
Hide resolved
...kages/e2e-tests/test-applications/nextjs-16-pages-dir/pages/pages-router/ssr-error-class.tsx
Outdated
Show resolved
Hide resolved
...packages/e2e-tests/test-applications/nextjs-16-pages-dir/pages/pages-router/ssr-error-fc.tsx
Outdated
Show resolved
Hide resolved
dev-packages/e2e-tests/test-applications/nextjs-16-pages-dir/proxy.ts
Outdated
Show resolved
Hide resolved
| // as the runtime freezes as soon as the error is thrown below | ||
| await flushSafelyWithTimeout(); | ||
|
|
||
| // We rethrow here so that nextjs can do with the error whatever it would normally do. (Sometimes "whatever it | ||
| // would normally do" is to allow the error to bubble up to the global handlers - another reason we need to mark | ||
| // the error as already having been captured.) | ||
| throw objectifiedErr; | ||
| } | ||
| }, | ||
| }); | ||
| } |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I switched to a blocking await here before throwing which should work better than calling waitUntil then throwing as the runtime can shutdown as soon as an unhandled error like these are thrown.
This matches the logic we have in the other API handler wrapper.
949da51 to
bdb4be3
Compare
6de8d44 to
9c04b47
Compare
| // Set transaction name on isolation scope to ensure parameterized routes are used | ||
| // The HTTP server integration sets it on isolation scope, so we need to match that | ||
| const method = event.request?.method || 'GET'; | ||
| path = path ?? event.request?.url ?? '/'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Nullish coalescing won't handle empty path string
The path variable is assigned from String(...).replace(...).trim() on line 161, which always returns a string (possibly empty ""). On line 165, path = path ?? event.request?.url ?? '/' uses nullish coalescing (??), which only falls back for null/undefined, not for empty strings. If the span name is exactly 'executing api route (pages)' with no route suffix, path becomes "" and the fallback to event.request?.url or / never triggers. This results in malformed transaction names like "GET " instead of "GET /". Using the logical OR operator (||) would correctly handle empty strings.
4538dfe to
ecfe19b
Compare
This is a big PR because of the tests added, the logic changes themselves are pretty minimal, so make sure to filter out the files when reviewing.
Actual Changes
Removed traces from
wrapApiHandlerWithSentryfor both the server runtime and the edge runtimeTests Added
Since we are dropping explicit trace wrapping logic from the pages router templates, we needed to have tests on Next 16 to make sure the page router there still works in both Turbopack and Webpack with minimal differences in the quality of the traces.
We have around 36 test case to check, but only 20 can pass at this time due to the wrapping logic still present, ideally as we move towards removing templates entirely, we can then unskip those tests and tighten many of the assertions we have to accommodate for it.
I added TODOs and a
TEST_STATUS.mddocument to detail what we should update once the SDK drops more of the wrapping logic it currently has.Closes #18450 (added automatically)